package com.example.util;

import org.apache.shiro.authc.AuthenticationException;
import org.springframework.util.DigestUtils;

import java.util.Random;

/**
 * 密码加密和校验的工具类
 */
public class CredentialsUtils {

    private static final Random RANDOM = new Random();

    /**
     * 生成16位随机数字字符串Salt
     * @return
     */
    public static String randomSalt() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 16; i++) {
            sb.append(RANDOM.nextInt(10)); // 0 - 9
        }
        return sb.toString();
    }

    public static String cryptPassword(String password, String salt) {
        // 加密原始密码，例如123456
        String md5Pwd = DigestUtils.md5DigestAsHex(password.getBytes());
        // 转换成32位字符的字符数组
        char[] pwdArr = md5Pwd.toCharArray(); // 32
        // salt字符串直接转换成16位字符串的字符数组
        char[] saltArr = salt.toCharArray(); // 16
        // 如果salt出现脏数据，抛出一个异常
        if (saltArr.length != 16) {
            throw new AuthenticationException("数据库数据异常，请联系管理员");
        }
        // 定义新的密码数组，字符48个使用上面2个穿插结合
        char[] newPwdArr = new char[pwdArr.length + saltArr.length];
        for (int i = 0; i < saltArr.length; i++) {
            // 以i等于0为例
            // newPwdArr[0] = pwdArr[0]
            newPwdArr[3 * i] = pwdArr[2 * i];
            // newPwdArr[1] = pwdArr[1]
            newPwdArr[3 * i + 1] = pwdArr[2 * i + 1];
            // newPwdArr[2] = saltArr[0]
            newPwdArr[3 * i + 2] = saltArr[i];
        }
        // 拼接完成的48位字符串，已经具备了salt
        String saltPwd = new String(newPwdArr);
        // 再进行一次MD5加密，得到32位的最终密码
        return DigestUtils.md5DigestAsHex(saltPwd.getBytes());
    }

    /**
     * 用于更新密码
     * @param args
     */
    public static void main(String[] args) {
        String password = "123456";
        String salt = randomSalt(); // 存数据库
        salt = "1812974845942700";
        String cryptPassword = cryptPassword(password, salt); // 存数据库
        System.out.println(password);
        System.out.println(salt);
        System.out.println(cryptPassword);
    }
}
